package com.leo.shiro;

import com.leo.model.User;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;

import java.util.*;

/**
 * @ClassName: MyShiroRealm
 * @Description: shiro的授权鉴权
 * @Author: leo825
 * @Date: 2020-08-01 11:16
 * @Version: 1.0
 **/
public class MyShiroRealm extends AuthorizingRealm {

    private static Map<String,User> userMap = new HashMap<String, User>();
    static{
//        userMap.put("jack", new User("jack","aaa123"));
//        userMap.put("tom", new User("tom","bbb321"));
//        userMap.put("jean", new User("jean","ccc213"));
        //使用Map模拟数据库获取User表信息
        userMap.put("jack", new User("jack","43e66616f8730a08e4bf1663301327b1"));
        userMap.put("tom", new User("tom","3abee8ced79e15b9b7ddd43b95f02f95"));
        userMap.put("jean", new User("jean","1a287acb0d87baded1e79f4b4c0d4f3e"));


    }
    /***
     * 授权
     * @param
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        Object principal = principals.getPrimaryPrincipal();

        Set<String> roles = new HashSet<>();
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        if ("admin".equals(principal.toString())) {
            roles.add("admin");
            info.setRoles(roles);
            info.addStringPermissions(Arrays.asList("admin:*"));
        } else if ("user".equals(principal.toString())) {
            roles.add("user");
            info.setRoles(roles);
            info.addStringPermissions(Arrays.asList("user:*"));
        }
        return info;
    }

    /****
     * 认证
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(
            AuthenticationToken token) throws AuthenticationException {
        //1.把AuthenticationToken转换为UsernamePasswordToken
        UsernamePasswordToken userToken = (UsernamePasswordToken) token;

        //2.从UsernamePasswordToken中获取username
        String username = userToken.getUsername();

        //3.调用数据库的方法，从数据库中查询Username对应的用户记录
        System.out.println("从数据看中获取UserName为"+username+"所对应的信息。");
        //Map模拟数据库取数据
        User u = userMap.get(username);

        //4.若用户不行存在，可以抛出UnknownAccountException
        if(u==null){
            throw new UnknownAccountException("用户不存在");
        }

        //5.若用户被锁定，可以抛出LockedAccountException
//        if(u.isLocked()){
//            throw new LockedAccountException("用户被锁定");
//        }

        //7.根据用户的情况，来构建AuthenticationInfo对象,通常使用的实现类为SimpleAuthenticationInfo
        //以下信息是从数据库中获取的
        //1)principal：认证的实体信息，可以是username，也可以是数据库表对应的用户的实体对象
        Object principal = u.getUserName();
        //2)credentials：密码
        Object credentials = u.getPassword();
        //3)realmName：当前realm对象的name，调用父类的getName()方法即可
        String realmName = getName();
        //4)credentialsSalt盐值
        ByteSource credentialsSalt = ByteSource.Util.bytes(principal);//使用账号作为盐值

        SimpleAuthenticationInfo info = null; //new SimpleAuthenticationInfo(principal,credentials,realmName);
        info = new SimpleAuthenticationInfo(principal, credentials, credentialsSalt, realmName);
        return info;
    }

//    //main方法生成加密后的密码
//    public static void main(String[] args) {
//        User u = null;
//        Iterator<String> it = userMap.keySet().iterator();
//        while(it.hasNext()){
//            u = userMap.get(it.next());
//            String hashAlgorithmName = "MD5";//加密方式
//            Object crdentials = u.getPassword();//密码原值
//            ByteSource salt = ByteSource.Util.bytes(u.getUserName());//以账号作为盐值
//            int hashIterations = 1024;//加密1024次
//            Object result = new SimpleHash(hashAlgorithmName,crdentials,salt,hashIterations);
//            System.out.println(u.getUserName()+":"+result);
//        }
//    }
}